{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "\n",
    "## Datawhale十二月组队学习 Pandas\n",
    "## 第一次打卡 \n",
    "## 预备知识"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "## 一、Python基础\n",
    "### 1. 列表推导式与条件赋值\n",
    "\n",
    "在生成一个数字序列的时候，在`Python`中可以如下写出："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Looking in indexes: https://mirror.baidu.com/pypi/simple/\n",
      "Collecting pandas==1.1.5\n",
      "\u001b[?25l  Downloading https://mirror.baidu.com/pypi/packages/fd/70/e8eee0cbddf926bf51958c7d6a86bc69167c300fa2ba8e592330a2377d1b/pandas-1.1.5-cp37-cp37m-manylinux1_x86_64.whl (9.5MB)\n",
      "\u001b[K     |████████████████████████████████| 9.5MB 22.4MB/s eta 0:00:01\n",
      "\u001b[?25hRequirement already satisfied: python-dateutil>=2.7.3 in /opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages (from pandas==1.1.5) (2.8.0)\n",
      "Requirement already satisfied: pytz>=2017.2 in /opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages (from pandas==1.1.5) (2019.3)\n",
      "Requirement already satisfied: numpy>=1.15.4 in /opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages (from pandas==1.1.5) (1.16.4)\n",
      "Requirement already satisfied: six>=1.5 in /opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages (from python-dateutil>=2.7.3->pandas==1.1.5) (1.15.0)\n",
      "Installing collected packages: pandas\n",
      "  Found existing installation: pandas 0.23.4\n",
      "    Uninstalling pandas-0.23.4:\n",
      "      Successfully uninstalled pandas-0.23.4\n",
      "Successfully installed pandas-1.1.5\n"
     ]
    }
   ],
   "source": [
    "!pip install pandas==1.1.5"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[0, 2, 4, 6, 8]"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "L = []\n",
    "def my_func(x):\n",
    "    return 2*x\n",
    "for i in range(5):\n",
    "    L.append(my_func(i))\n",
    "L"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "事实上可以利用列表推导式进行写法上的简化：`[* for i in *]`。其中，第一个`*`为映射函数，其输入为后面`i`指代的内容，第二个`*`表示迭代的对象。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[[0, 2, 4, 6, 8]]"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "L=[]\r\n",
    "L.append([my_func(i) for i in range(5)])\r\n",
    "L"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[0, 2, 4, 6, 8]"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "[my_func(i) for i in range(5)]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "列表表达式还支持多层嵌套，如下面的例子中第一个`for`为外层循环，第二个为内层循环："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['a_c', 'a_d', 'b_c', 'b_d']"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "[m+'_'+n for m in ['a', 'b'] for n in ['c', 'd']]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "除了列表推导式，另一个实用的语法糖是条件赋值，其形式为`value = a if condition else b`："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'cat'"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "value = 'cat' if 2>1 else 'dog'\n",
    "value"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'cat'"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#一般的写法：\r\n",
    "a,b = 'cat','dog'\r\n",
    "flag = True\r\n",
    "#flag = 2>1\r\n",
    "if flag:\r\n",
    "    value = a\r\n",
    "else:\r\n",
    "    value = b\r\n",
    "value\r\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "下面举一个例子，截断列表中超过5的元素："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1, 2, 3, 4, 5, 'NaN', 'NaN']"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "L = [1, 2, 3, 4, 5, 6, 7]\n",
    "[i if i <= 5 else 'NaN' for i in L]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "### 2. 匿名函数与map方法\n",
    "\n",
    "有一些函数的定义具有清晰简单的映射关系，例如上面的`my_func`函数，这时候可以用匿名函数的方法简洁地表示："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "9"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "my_func = lambda x: x*x\n",
    "my_func(3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "multi_para_func = lambda a, b: a + b\n",
    "multi_para_func(1, 2) "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "但上面的用法其实违背了“匿名”的含义，事实上它往往在无需多处调用的场合进行使用，例如上面列表推导式中的例子，用户不关心函数的名字，只关心这种映射的关系："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[0, 1, 4, 9, 16]"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "[(lambda x: x*x)(i) for i in range(5)]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "对于上述的这种列表推导式的匿名函数映射，`Python`中提供了`map`函数来完成，它返回的是一个`map`对象，需要通过`list`转为列表：\n",
    "map对象：\n",
    "\n",
    "map(function, iterable, ...)\n",
    "\n",
    "返回一个将 function 应用于 iterable 中每一项并输出其结果的迭代器。如果传入了额外的 iterable 参数，function 必须接受相同个数的实参并被应用于从所有可迭代对象中并行获取的项。当有多个可迭代对象时，最短的可迭代对象耗尽则整个迭代就将结束。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<map at 0x7fe701ae9490>"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "map(lambda x: 2*x, range(5))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[0, 2, 4, 6, 8]"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "list(map(lambda x: 2*x, range(5)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "对于多个输入值的函数映射，可以通过追加迭代对象实现："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['0___a', '1___b', '2___c', '3___d', '4___e']"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "list(map(lambda x, y: str(x)+'___'+y, range(5), list('abcde')))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "### 3. zip对象与enumerate方法\n",
    "\n",
    "`zip`函数能够把多个可迭代对象打包成一个元组构成的可迭代对象，它返回了一个`zip`对象，通过`tuple`, `list`可以得到相应的打包结果："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "139960534244320\n",
      "139960528738736\n"
     ]
    }
   ],
   "source": [
    "L1, L2, L3 = list('abc'), list('def'), list('hij')\n",
    "L4 = list(zip(L1, L2, L3))\n",
    "L4\n",
    "#这里看看地址变化\n",
    "print(id(L4))\n",
    "print(id(L1))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(('a', 'd', 'h'), ('b', 'e', 'i'), ('c', 'f', 'j'))"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tuple(zip(L1, L2, L3))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "往往会在循环迭代的时候使用到`zip`函数："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "a d h\n",
      "b e i\n",
      "c f j\n"
     ]
    }
   ],
   "source": [
    "for i, j, k in zip(L1, L2, L3):\n",
    "     print(i, j, k)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "`enumerate`是一种特殊的打包，它可以在迭代时绑定迭代元素的遍历序号："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0 a\n",
      "1 b\n",
      "2 c\n",
      "3 d\n"
     ]
    }
   ],
   "source": [
    "L = list('abcd')\n",
    "for index, value in enumerate(L):\n",
    "     print(index, value)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "用`zip`对象也能够简单地实现这个功能："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0 a\n",
      "1 b\n",
      "2 c\n",
      "3 d\n"
     ]
    }
   ],
   "source": [
    "for index, value in zip(range(4), L):\n",
    "     print(index, value)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "当需要对两个列表建立字典映射时，可以利用`zip`对象："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'a': 'd', 'b': 'e', 'c': 'f'}"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "dict(zip(L1, L2))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "既然有了压缩函数，那么`Python`也提供了`*`操作符和`zip`联合使用来进行解压操作：  \n",
    "*用于参数前面，表示传入的多个参数将按照元组的形式存储，是一个元组；  \n",
    "**用于参数前则表示传入的(多个)参数将按照字典的形式存储，是一个字典。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[('a', 'd', 'h'), ('b', 'e', 'i'), ('c', 'f', 'j')]"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "zipped = list(zip(L1, L2, L3))\n",
    "zipped"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[('a', 'b', 'c'), ('d', 'e', 'f'), ('h', 'i', 'j')]"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "list(zip(*zipped)) # 三个元组分别对应原来的列表"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "## 二、Numpy基础\n",
    "### 1. np数组的构造\n",
    "最一般的方法是通过`array`来构造："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1, 2, 3])"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import numpy as np\n",
    "np.array([1,2,3])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "下面讨论一些特殊数组的生成方式：\n",
    "\n",
    "【a】等差序列：`np.linspace`, `np.arange`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'\\nnp.linspace(\\n    start,\\n    stop,\\n    num=50,\\n    endpoint=True,\\n    retstep=False,\\n    dtype=None,\\n    axis=0,\\n)\\n'"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.linspace?\r\n",
    "#endpoint=False,最后一位不输出\r\n",
    "'''\r\n",
    "np.linspace(\r\n",
    "    start,\r\n",
    "    stop,\r\n",
    "    num=50,\r\n",
    "    endpoint=True,\r\n",
    "    retstep=False,\r\n",
    "    dtype=None,\r\n",
    "    axis=0,\r\n",
    ")\r\n",
    "endpoint : bool, optional\r\n",
    "    If True, `stop` is the last sample. Otherwise, it is not included.\r\n",
    "    Default is True.\r\n",
    "retstep : bool, optional\r\n",
    "    If True, return (`samples`, `step`), where `step` is the spacing\r\n",
    "    between samples.\r\n",
    "endpoint和retstep好像不是很常用哉\r\n",
    "\r\n",
    "\r\n",
    "'''"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1. , 1.4, 1.8, 2.2, 2.6, 3. , 3.4, 3.8, 4.2, 4.6, 5. ])"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.linspace(1,5,11) # 起始、终止（包含）、样本个数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1, 3])"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.arange(1,5,2) # 起始、终止（不包含）、步长"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "【b】特殊矩阵：`zeros`, `eye`, `full`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0., 0., 0.],\n",
       "       [0., 0., 0.]])"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.zeros((2,3)) # 传入元组表示各维度大小"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1, 0, 0],\n",
       "       [0, 1, 0],\n",
       "       [0, 0, 1]])"
      ]
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.eye(3,dtype=int) # 3*3的单位矩阵"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0., 1., 0.],\n",
       "       [0., 0., 1.],\n",
       "       [0., 0., 0.]])"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.eye(3, k=1) # 偏移主对角线1个单位的伪单位矩阵"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "np.eye?\r\n",
    "'''\r\n",
    "np.eye(N, M=None, k=0, dtype=<class 'float'>, order='C')\r\n",
    "order : {'C', 'F'}, optional\r\n",
    "    Whether the output should be stored in row-major (C-style) or\r\n",
    "    column-major (Fortran-style) order in memory.\r\n",
    "行优先或者式列优先\r\n",
    "'''"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[0. 1. 0.]\n",
      " [0. 0. 1.]\n",
      " [0. 0. 0.]]\n",
      "[[0. 1. 0.]\n",
      " [0. 0. 1.]\n",
      " [0. 0. 0.]]\n",
      "139960370039664\n",
      "139960370038304\n"
     ]
    }
   ],
   "source": [
    "A = np.eye(3,k=1)\r\n",
    "B = np.eye(3,k=1,order='F')\r\n",
    "print(A)\r\n",
    "print(B)\r\n",
    "print(id(A))\r\n",
    "print(id(B))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[10, 10, 10],\n",
       "       [10, 10, 10]])"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.full((2,3), 10) # 元组传入大小，10表示填充数值"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1, 2, 3],\n",
       "       [1, 2, 3]])"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.full((2,3), [1,2,3]) # 通过传入列表填充每列的值"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "【c】随机矩阵：`np.random`\n",
    "\n",
    "最常用的随机生成函数为`rand`, `randn`, `randint`, `choice`，它们分别表示0-1均匀分布的随机数组、标准正态的随机数组、随机整数组和随机列表抽样："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0.53278509, 0.00283235, 0.28780472])"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.random.rand(3) # 生成服从0-1均匀分布的三个随机数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0.28264113, 0.20941578, 0.75822717],\n",
       "       [0.34805628, 0.9907254 , 0.3913556 ],\n",
       "       [0.5090322 , 0.1279164 , 0.92056387]])"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.random.rand(3, 3) # 注意这里传入的不是元组，每个维度大小分开输入"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 0.40041547, -0.20460424,  2.56150225])"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.random.randn(3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "4"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.random.randint(4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1"
      ]
     },
     "execution_count": 30,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.random.choice([1,2,3])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "对于服从区间`a`到`b`上的均匀分布可以如下生成："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([11.21650985,  8.05013868, 11.78426243])"
      ]
     },
     "execution_count": 34,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a, b = 5, 15\n",
    "(b - a) * np.random.rand(3) + a"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "`randn`生成了`N(0,I)`的标准正态分布："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([-1.45458052, -0.00385178, -0.72364504])"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.random.randn(3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0.86407903,  0.97629245],\n",
       "       [-0.12512098, -1.67306955]])"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.random.randn(2, 2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "对于服从方差为$\\sigma^2$均值为$\\mu$的一元正态分布可以如下生成："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([7.32248346, 7.87239753, 2.48473261])"
      ]
     },
     "execution_count": 35,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sigma, mu = 2.5, 3\n",
    "mu + np.random.randn(3) * sigma"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'\\nrandn(d0, d1, ..., dn)\\n\\nReturn a sample (or samples) from the \"standard normal\" distribution.\\n\\nFor random samples from :math:`N(\\\\mu, \\\\sigma^2)`, use:\\n\\n``sigma * np.random.randn(...) + mu``\\n\\n'"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.random.randn?\r\n",
    "'''\r\n",
    "randn(d0, d1, ..., dn)\r\n",
    "\r\n",
    "Return a sample (or samples) from the \"standard normal\" distribution.\r\n",
    "\r\n",
    "For random samples from :math:`N(\\mu, \\sigma^2)`, use:\r\n",
    "\r\n",
    "``sigma * np.random.randn(...) + mu``\r\n",
    "\r\n",
    "标准正态分布\r\n",
    "For random samples from :math:`N(\\mu, \\sigma^2)`, use:\r\n",
    "\r\n",
    "``sigma * np.random.randn(...) + mu``\r\n",
    "'''"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "`randint`可以指定生成随机整数的最小值最大值和维度大小："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[14,  8],\n",
       "       [ 6, 13]])"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "low, high, size = 5, 15, (2,2)\n",
    "np.random.randint(low, high, size)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'\\nrandint(low, high=None, size=None, dtype=\\'l\\')\\n\\nReturn random integers from `low` (inclusive) to `high` (exclusive).\\n\\nReturn random integers from the \"discrete uniform\" distribution of\\nthe specified dtype in the \"half-open\" interval [`low`, `high`). If\\n`high` is None (the default), then results are from [0, `low`).\\n\\nsize : int or tuple of ints, optional\\n    Output shape.  If the given shape is, e.g., ``(m, n, k)``, then\\n    ``m * n * k`` samples are drawn.  Default is None, in which case a\\n    single value is returned.\\n'"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.random.randint?\r\n",
    "'''\r\n",
    "randint(low, high=None, size=None, dtype='l')\r\n",
    "\r\n",
    "Return random integers from `low` (inclusive) to `high` (exclusive).\r\n",
    "\r\n",
    "Return random integers from the \"discrete uniform\" distribution of\r\n",
    "the specified dtype in the \"half-open\" interval [`low`, `high`). If\r\n",
    "`high` is None (the default), then results are from [0, `low`).\r\n",
    "\r\n",
    "size : int or tuple of ints, optional\r\n",
    "    Output shape.  If the given shape is, e.g., ``(m, n, k)``, then\r\n",
    "    ``m * n * k`` samples are drawn.  Default is None, in which case a\r\n",
    "    single value is returned.\r\n",
    "注意事项\r\n",
    "See Also\r\n",
    "--------\r\n",
    "random.random_integers : similar to `randint`, only for the closed\r\n",
    "    interval [`low`, `high`], and 1 is the lowest value if `high` is\r\n",
    "    omitted. In particular, this other one is the one to use to generate\r\n",
    "    uniformly distributed discrete non-integers.\r\n",
    "'''"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "`choice`可以从给定的列表中，以一定概率和方式抽取结果，当不指定概率时为均匀采样，默认抽取方式为有放回抽样："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "np.random.choice?\r\n",
    "'''\r\n",
    "choice(a, size=None, replace=True, p=None)\r\n",
    "\r\n",
    "Generates a random sample from a given 1-D array\r\n",
    "\r\n",
    "a : 1-D array-like or int\r\n",
    "    If an ndarray, a random sample is generated from its elements.\r\n",
    "    If an int, the random sample is generated as if a were np.arange(a)\r\n",
    "size : int or tuple of ints, optional\r\n",
    "    Output shape.  If the given shape is, e.g., ``(m, n, k)``, then\r\n",
    "    ``m * n * k`` samples are drawn.  Default is None, in which case a\r\n",
    "    single value is returned.\r\n",
    "replace : boolean, optional\r\n",
    "    Whether the sample is with or without replacement\r\n",
    "p : 1-D array-like, optional\r\n",
    "    The probabilities associated with each entry in a.\r\n",
    "    If not given the sample assumes a uniform distribution over all\r\n",
    "    entries in a.\r\n",
    "其中关键是replace是否放回抽样，size是选择输出的形状\r\n",
    "Returns\r\n",
    "--------\r\n",
    "samples : single item or ndarray\r\n",
    "    The generated random samples"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array(['d', 'b'], dtype='<U1')"
      ]
     },
     "execution_count": 41,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "my_list = ['a', 'b', 'c', 'd']\n",
    "np.random.choice(my_list, 2, replace=False, p=[0.1, 0.7, 0.1 ,0.1])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([['a', 'b', 'a'],\n",
       "       ['b', 'b', 'c'],\n",
       "       ['a', 'b', 'a']], dtype='<U1')"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.random.choice(my_list, (3,3))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "当返回的元素个数与原列表相同时，等价于使用`permutation`函数，即打散原列表："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array(['c', 'a', 'b', 'd'], dtype='<U1')"
      ]
     },
     "execution_count": 42,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.random.permutation(my_list)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "最后，需要提到的是随机种子，它能够固定随机数的输出结果："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.5488135039273248"
      ]
     },
     "execution_count": 45,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#固定随机种子方便复现\n",
    "np.random.seed(0)\n",
    "np.random.rand()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.8034280400796879"
      ]
     },
     "execution_count": 46,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.random.seed(999)\n",
    "np.random.rand()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "### 2. np数组的变形与合并\n",
    "【a】转置：`T`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0., 0.],\n",
       "       [0., 0.],\n",
       "       [0., 0.]])"
      ]
     },
     "execution_count": 51,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.zeros((2,3)).T"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "【b】合并操作：`r_`, `c_`\n",
    "\n",
    "对于二维数组而言，`r_`和`c_`分别表示上下合并和左右合并："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0., 0., 0.],\n",
       "       [0., 0., 0.],\n",
       "       [0., 0., 0.],\n",
       "       [0., 0., 0.]])"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.r_[np.zeros((2,3)),np.zeros((2,3))]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0., 0., 0., 0., 0., 0.],\n",
       "       [0., 0., 0., 0., 0., 0.]])"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.c_[np.zeros((2,3)),np.zeros((2,3))]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "一维数组和二维数组进行合并时，应当把其视作列向量，在长度匹配的情况下只能够使用左右合并的`c_`操作："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "\"\\nOptional character strings placed as the first element of the index\\nexpression can be used to change the output. The strings 'r' or 'c' result\\nin matrix output. If the result is 1-D and 'r' is specified a 1 x N (row)\\nmatrix is produced. If the result is 1-D and 'c' is specified, then a N x 1\\n(column) matrix is produced. If the result is 2-D then both provide the\\nsame matrix result.\\n\""
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.r_?\r\n",
    "'''\r\n",
    "\r\n",
    "This is a simple way to build up arrays quickly. There are two use cases.\r\n",
    "\r\n",
    "1. If the index expression contains comma separated arrays, then stack\r\n",
    "   them along their first axis.\r\n",
    "2. If the index expression contains slice notation or scalars then create\r\n",
    "   a 1-D array with a range indicated by the slice notation.\r\n",
    "\r\n",
    "If slice notation is used, the syntax ``start:stop:step`` is equivalent\r\n",
    "to ``np.arange(start, stop, step)`` inside of the brackets. However, if\r\n",
    "``step`` is an imaginary number (i.e. 100j) then its integer portion is\r\n",
    "interpreted as a number-of-points desired and the start and stop are\r\n",
    "inclusive. In other words ``start:stop:stepj`` is interpreted as\r\n",
    "``np.linspace(start, stop, step, endpoint=1)`` inside of the brackets.\r\n",
    "After expansion of slice notation, all comma separated sequences are\r\n",
    "concatenated together.\r\n",
    "\r\n",
    "Optional character strings placed as the first element of the index\r\n",
    "expression can be used to change the output. The strings 'r' or 'c' result\r\n",
    "in matrix output. If the result is 1-D and 'r' is specified a 1 x N (row)\r\n",
    "matrix is produced. If the result is 1-D and 'c' is specified, then a N x 1\r\n",
    "(column) matrix is produced. If the result is 2-D then both provide the\r\n",
    "same matrix result.\r\n",
    "\r\n",
    "A string integer specifies which axis to stack multiple comma separated\r\n",
    "arrays along. A string of two comma-separated integers allows indication\r\n",
    "of the minimum number of dimensions to force each entry into as the\r\n",
    "second integer (the axis to concatenate along is still the first integer).\r\n",
    "\r\n",
    "A string with three comma-separated integers allows specification of the\r\n",
    "axis to concatenate along, the minimum number of dimensions to force the\r\n",
    "entries to, and which axis should contain the start of the arrays which\r\n",
    "are less than the specified number of dimensions. In other words the third\r\n",
    "integer allows you to specify where the 1's should be placed in the shape\r\n",
    "of the arrays that have their shapes upgraded. By default, they are placed\r\n",
    "in the front of the shape tuple. The third argument allows you to specify\r\n",
    "where the start of the array should be instead. Thus, a third argument of\r\n",
    "'0' would place the 1's at the end of the array shape. Negative integers\r\n",
    "specify where in the new shape tuple the last dimension of upgraded arrays\r\n",
    "should be placed, so the default is '-1'.\r\n",
    "\r\n",
    "这段话的最有意思的就是最后一段对1和-1的表述\r\n",
    "'''"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "ValueError('all the input arrays must have same number of dimensions')"
      ]
     },
     "execution_count": 53,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "try:\n",
    "     np.r_[np.array([0,0]),np.zeros((2,1))]\n",
    "except Exception as e:\n",
    "     Err_Msg = e\n",
    "Err_Msg\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0., 0., 0., 0.])"
      ]
     },
     "execution_count": 55,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.r_[np.array([0,0]),np.zeros(2)]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0., 0., 0., 0.],\n",
       "       [0., 0., 0., 0.]])"
      ]
     },
     "execution_count": 56,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.c_[np.array([0,0]),np.zeros((2,3))]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "【c】维度变换：`reshape`\n",
    "\n",
    "`reshape`能够帮助用户把原数组按照新的维度重新排列。在使用时有两种模式，分别为`C`模式和`F`模式，分别以逐行和逐列的顺序进行填充读取。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0, 1],\n",
       "       [2, 3],\n",
       "       [4, 5],\n",
       "       [6, 7]])"
      ]
     },
     "execution_count": 57,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "target = np.arange(8).reshape(4,2)\n",
    "target"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0, 1],\n",
       "       [2, 3],\n",
       "       [4, 5],\n",
       "       [6, 7]])"
      ]
     },
     "execution_count": 58,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "target.reshape((4,2), order='C') # 按照行读取和填充"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0, 1],\n",
       "       [2, 3],\n",
       "       [4, 5],\n",
       "       [6, 7]])"
      ]
     },
     "execution_count": 59,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "target.reshape((4,2), order='F') # 按照列读取和填充"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "特别地，由于被调用数组的大小是确定的，`reshape`允许有一个维度存在空缺，此时只需填充-1即可：  \n",
    "也就是自动算好另外一个维度"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0, 1],\n",
       "       [2, 3],\n",
       "       [4, 5],\n",
       "       [6, 7]])"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "target.reshape((4,-1))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "下面将`n*1`大小的数组转为1维数组的操作是经常使用的："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1.],\n",
       "       [1.],\n",
       "       [1.]])"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "target = np.ones((3,1))\n",
    "target"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1., 1., 1.])"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "target.reshape(-1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "np.reshape?\r\n",
    "'''\r\n",
    "a : array_like\r\n",
    "    Array to be reshaped.\r\n",
    "newshape : int or tuple of ints\r\n",
    "    The new shape should be compatible with the original shape. If\r\n",
    "    an integer, then the result will be a 1-D array of that length.\r\n",
    "    One shape dimension can be -1. In this case, the value is\r\n",
    "    inferred from the length of the array and remaining dimensions.\r\n",
    "order : {'C', 'F', 'A'}, optional\r\n",
    "    Read the elements of `a` using this index order, and place the\r\n",
    "    elements into the reshaped array using this index order.  'C'\r\n",
    "    means to read / write the elements using C-like index order,\r\n",
    "    with the last axis index changing fastest, back to the first\r\n",
    "    axis index changing slowest. 'F' means to read / write the\r\n",
    "    elements using Fortran-like index order, with the first index\r\n",
    "    changing fastest, and the last index changing slowest. Note that\r\n",
    "    the 'C' and 'F' options take no account of the memory layout of\r\n",
    "    the underlying array, and only refer to the order of indexing.\r\n",
    "    'A' means to read / write the elements in Fortran-like index\r\n",
    "    order if `a` is Fortran *contiguous* in memory, C-like order\r\n",
    "    otherwise.\r\n",
    "最长的一段翻译就是C模式和Fortran模式，分别是从最后一行开始读和第一行开始读，在内存占用上没有区别\r\n",
    "A模式是使用Fortran的列优先的顺序，如果在内存中数组是连续存储的。\r\n",
    "'''\r\n",
    "\r\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "139960370042160\n",
      "139960370041440\n"
     ]
    }
   ],
   "source": [
    "A=target.reshape((4,2), order='C')\r\n",
    "B=target.reshape((4,2), order='F')\r\n",
    "print(id(A))\r\n",
    "print(id(B))\r\n",
    "#地址不一样"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "### 3. np数组的切片与索引\n",
    "数组的切片模式支持使用`slice`类型的`start:end:step`切片，还可以直接传入列表指定某个维度的索引进行切片："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0, 1, 2],\n",
       "       [3, 4, 5],\n",
       "       [6, 7, 8]])"
      ]
     },
     "execution_count": 62,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "target = np.arange(9).reshape(3,3)\n",
    "target"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 63,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0, 2],\n",
       "       [3, 5]])"
      ]
     },
     "execution_count": 63,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "target[:-1, [0,2]]\r\n",
    "#切割到倒数第一维，切割第0和第2列"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "此外，还可以利用`np.ix_`在对应的维度上使用布尔索引，但此时不能使用`slice`切片："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'\\nThis function takes N 1-D sequences and returns N outputs with N\\ndimensions each, such that the shape is 1 in all but one dimension\\nand the dimension with the non-unit shape value cycles through all\\nN dimensions.\\n\\nUsing `ix_` one can quickly construct index arrays that will index\\nthe cross product. ``a[np.ix_([1,3],[2,5])]`` returns the array\\n``[[a[1,2] a[1,5]], [a[3,2] a[3,5]]]``.\\n\\nout : tuple of ndarrays\\n    N arrays with N dimensions each, with N the number of input\\n    sequences. Together these arrays form an open mesh.\\n'"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.ix_?\r\n",
    "'''\r\n",
    "This function takes N 1-D sequences and returns N outputs with N\r\n",
    "dimensions each, such that the shape is 1 in all but one dimension\r\n",
    "and the dimension with the non-unit shape value cycles through all\r\n",
    "N dimensions.\r\n",
    "\r\n",
    "Using `ix_` one can quickly construct index arrays that will index\r\n",
    "the cross product. ``a[np.ix_([1,3],[2,5])]`` returns the array\r\n",
    "``[[a[1,2] a[1,5]], [a[3,2] a[3,5]]]``.\r\n",
    "\r\n",
    "out : tuple of ndarrays\r\n",
    "    N arrays with N dimensions each, with N the number of input\r\n",
    "    sequences. Together these arrays form an open mesh.\r\n",
    "'''"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0, 2],\n",
       "       [6, 8]])"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "target[np.ix_([True, False, True], [True, False, True])]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[3, 5],\n",
       "       [6, 8]])"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "target[np.ix_([1,2], [True, False, True])]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "当数组维度为1维时，可以直接进行布尔索引，而无需`np.ix_`："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0, 2, 4, 6, 8])"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "new = target.reshape(-1)\n",
    "new[new%2==0]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "### 4. 常用函数\n",
    "为了简单起见，这里假设下述函数输入的数组都是一维的。\n",
    "\n",
    "【a】`where`\n",
    "\n",
    "`where`是一种条件函数，可以指定满足条件与不满足条件位置对应的填充值："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 96,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([5, 1, 5, 5])"
      ]
     },
     "execution_count": 96,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = np.array([-1,1,-1,0])\n",
    "np.where(a>0, a, 5) # 对应位置为True时填充a对应元素，否则填充5"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 98,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[5 1 5 5]\n"
     ]
    }
   ],
   "source": [
    "#改写成普通的if\r\n",
    "B=np.array([0,0,0,0])\r\n",
    "for i in range(4):\r\n",
    "    B[i] = a[i] if a[i]>0 else 5\r\n",
    "print(B)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "【b】`nonzero`, `argmax`, `argmin`\n",
    "\n",
    "这三个函数返回的都是索引，`nonzero`返回非零数的索引，`argmax`, `argmin`分别返回最大和最小数的索引："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 100,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([0, 1, 3, 4, 5]),)"
      ]
     },
     "execution_count": 100,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = np.array([-2,-5,0,1,3,-1])\n",
    "np.nonzero(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 101,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "4"
      ]
     },
     "execution_count": 101,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a.argmax()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 102,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1"
      ]
     },
     "execution_count": 102,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a.argmin()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "【c】`any`, `all`\n",
    "\n",
    "`any`指当序列至少 **存在一个** `True`或非零元素时返回`True`，否则返回`False`\n",
    "\n",
    "`all`指当序列元素 **全为** `True`或非零元素时返回`True`，否则返回`False`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = np.array([0,1])\n",
    "a.any()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    " a.all()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'\\nTest whether any array element along a given axis evaluates to True.\\n\\nReturns single boolean unless `axis` is not ``None``\\n输出的True False都在内存的同一位置\\n'"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.any?\r\n",
    "'''\r\n",
    "Test whether any array element along a given axis evaluates to True.\r\n",
    "\r\n",
    "Returns single boolean unless `axis` is not ``None``\r\n",
    "输出的True False都在内存的同一位置\r\n",
    "'''"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "【d】`cumprod`, `cumsum`, `diff`\n",
    "\n",
    "`cumprod`, `cumsum`分别表示累乘和累加函数，返回同长度的数组，`diff`表示和前一个元素做差，由于第一个元素为缺失值，因此在默认参数情况下，返回长度是原数组减1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 106,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1, 2, 6])"
      ]
     },
     "execution_count": 106,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = np.array([1,2,3])\n",
    "a.cumprod()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 107,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1, 3, 6])"
      ]
     },
     "execution_count": 107,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a.cumsum()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 108,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([1, 1])"
      ]
     },
     "execution_count": 108,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.diff(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "np.diff?\r\n",
    "'''\r\n",
    "np.diff(a, n=1, axis=-1, prepend=<no value>, append=<no value>)\r\n",
    "a : array_like\r\n",
    "    Input array\r\n",
    "n : int, optional\r\n",
    "    The number of times values are differenced. If zero, the input\r\n",
    "    is returned as-is.\r\n",
    "axis : int, optional\r\n",
    "    The axis along which the difference is taken, default is the\r\n",
    "    last axis.\r\n",
    "prepend, append : array_like, optional\r\n",
    "    Values to prepend or append to \"a\" along axis prior to\r\n",
    "    performing the difference.  Scalar values are expanded to\r\n",
    "    arrays with length 1 in the direction of axis and the shape\r\n",
    "    of the input array in along all other axes.  Otherwise the\r\n",
    "    dimension and shape must match \"a\" except along axis.\r\n",
    "其中的关键axis是选择在哪条轴上做差\r\n",
    ">>> x = np.array([[1, 3, 6, 10], [0, 5, 6, 8]])\r\n",
    ">>> np.diff(x)\r\n",
    "array([[2, 3, 4],\r\n",
    "       [5, 1, 2]])\r\n",
    ">>> np.diff(x, axis=0)\r\n",
    "array([[-1,  2,  0, -2]])\r\n",
    "这是在横向和纵向做差的比较\r\n",
    "\r\n",
    "Returns\r\n",
    "-------\r\n",
    "diff : ndarray\r\n",
    "    The n-th differences. The shape of the output is the same as `a`\r\n",
    "    except along `axis` where the dimension is smaller by `n`. The\r\n",
    "    type of the output is the same as the type of the difference\r\n",
    "    between any two elements of `a`. This is the same as the type of\r\n",
    "    `a` in most cases. A notable exception is `datetime64`, which\r\n",
    "    results in a `timedelta64` output array.\r\n",
    "'''"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "【e】 统计函数\n",
    "\n",
    "常用的统计函数包括`max, min, mean, median, std, var, sum, quantile`，其中分位数计算是全局方法，因此不能通过`array.quantile`的方法调用："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 109,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0, 1, 2, 3, 4])"
      ]
     },
     "execution_count": 109,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "target = np.arange(5)\n",
    "target"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "4"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "target.max()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 110,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2.0"
      ]
     },
     "execution_count": 110,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.quantile(target, 0.5) # 0.5分位数"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "但是对于含有缺失值的数组，它们返回的结果也是缺失值，如果需要略过缺失值，必须使用`nan*`类型的函数，上述的几个统计函数都有对应的`nan*`函数。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 111,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 1.,  2., nan])"
      ]
     },
     "execution_count": 111,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "target = np.array([1, 2, np.nan])\n",
    "target"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "nan"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "target.max()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 112,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2.0"
      ]
     },
     "execution_count": 112,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.nanmax(target)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1.5"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.nanquantile(target, 0.5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "\"\\nnp.quantile(\\n    a,\\n    q,\\n    axis=None,\\n    out=None,\\n    overwrite_input=False,\\n    interpolation='linear',\\n    keepdims=False,\\n)\\n计算方式：\\ninterpolation : {'linear', 'lower', 'higher', 'midpoint', 'nearest'}\\n    This optional parameter specifies the interpolation method to\\n    use when the desired quantile lies between two data points\\n    ``i < j``:\\n\\n        * linear: ``i + (j - i) * fraction``, where ``fraction``\\n          is the fractional part of the index surrounded by ``i``\\n          and ``j``.\\n        * lower: ``i``.\\n        * higher: ``j``.\\n        * nearest: ``i`` or ``j``, whichever is nearest.\\n        * midpoint: ``(i + j) / 2``.\\n\""
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.quantile?\r\n",
    "'''\r\n",
    "np.quantile(\r\n",
    "    a,\r\n",
    "    q,\r\n",
    "    axis=None,\r\n",
    "    out=None,\r\n",
    "    overwrite_input=False,\r\n",
    "    interpolation='linear',\r\n",
    "    keepdims=False,\r\n",
    ")\r\n",
    "计算方式：\r\n",
    "interpolation : {'linear', 'lower', 'higher', 'midpoint', 'nearest'}\r\n",
    "    This optional parameter specifies the interpolation method to\r\n",
    "    use when the desired quantile lies between two data points\r\n",
    "    ``i < j``:\r\n",
    "\r\n",
    "        * linear: ``i + (j - i) * fraction``, where ``fraction``\r\n",
    "          is the fractional part of the index surrounded by ``i``\r\n",
    "          and ``j``.\r\n",
    "        * lower: ``i``.\r\n",
    "        * higher: ``j``.\r\n",
    "        * nearest: ``i`` or ``j``, whichever is nearest.\r\n",
    "        * midpoint: ``(i + j) / 2``.\r\n",
    "'''\r\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "对于协方差和相关系数分别可以利用`cov, corrcoef`如下计算："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 114,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 11.66666667, -16.66666667],\n",
       "       [-16.66666667,  38.66666667]])"
      ]
     },
     "execution_count": 114,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "target1 = np.array([1,3,5,9])\n",
    "target2 = np.array([1,5,3,-9])\n",
    "np.cov(target1, target2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'\\nnp.cov(\\n    m,\\n    y=None,\\n    rowvar=True,\\n    bias=False,\\n    ddof=None,\\n    fweights=None,\\n    aweights=None,\\n)\\nbias : bool, optional\\n    Default normalization (False) is by ``(N - 1)``, where ``N`` is the\\n    number of observations given (unbiased estimate). If `bias` is True,\\n    then normalization is by ``N``. These values can be overridden by using\\n    the keyword ``ddof`` in numpy versions >= 1.5.\\nbias是用N还是N-1的选项\\n计算方式：\\n    >>> w = f * a\\n    >>> v1 = np.sum(w)\\n    >>> v2 = np.sum(w * a)\\n    >>> m -= np.sum(m * w, axis=1, keepdims=True) / v1\\n    >>> cov = np.dot(m * w, m.T) * v1 / (v1**2 - ddof * v2)\\n\\n'"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.cov?\r\n",
    "'''\r\n",
    "np.cov(\r\n",
    "    m,\r\n",
    "    y=None,\r\n",
    "    rowvar=True,\r\n",
    "    bias=False,\r\n",
    "    ddof=None,\r\n",
    "    fweights=None,\r\n",
    "    aweights=None,\r\n",
    ")\r\n",
    "bias : bool, optional\r\n",
    "    Default normalization (False) is by ``(N - 1)``, where ``N`` is the\r\n",
    "    number of observations given (unbiased estimate). If `bias` is True,\r\n",
    "    then normalization is by ``N``. These values can be overridden by using\r\n",
    "    the keyword ``ddof`` in numpy versions >= 1.5.\r\n",
    "bias是用N还是N-1的选项\r\n",
    "计算方式：\r\n",
    "    >>> w = f * a\r\n",
    "    >>> v1 = np.sum(w)\r\n",
    "    >>> v2 = np.sum(w * a)\r\n",
    "    >>> m -= np.sum(m * w, axis=1, keepdims=True) / v1\r\n",
    "    >>> cov = np.dot(m * w, m.T) * v1 / (v1**2 - ddof * v2)\r\n",
    "\r\n",
    "'''"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 116,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 1.        , -0.78470603],\n",
       "       [-0.78470603,  1.        ]])"
      ]
     },
     "execution_count": 116,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.corrcoef(target1, target2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'\\n计算式：R_{ij} = \\x0crac{ C_{ij} } { \\\\sqrt{ C_{ii} * C_{jj} } }\\nnp.corrcoef(x, y=None, rowvar=True, bias=<no value>, ddof=<no value>)\\nx : array_like\\n    A 1-D or 2-D array containing multiple variables and observations.\\n    Each row of `x` represents a variable, and each column a single\\n    observation of all those variables. Also see `rowvar` below.\\ny : array_like, optional\\n    An additional set of variables and observations. `y` has the same\\n    shape as `x`.\\nrowvar : bool, optional\\n    If `rowvar` is True (default), then each row represents a\\n    variable, with observations in the columns. Otherwise, the relationship\\n    is transposed: each column represents a variable, while the rows\\n    contain observations.\\nbias : _NoValue, optional\\n    Has no effect, do not use.\\n'"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.corrcoef?\r\n",
    "'''\r\n",
    "计算式：R_{ij} = \\frac{ C_{ij} } { \\sqrt{ C_{ii} * C_{jj} } }\r\n",
    "np.corrcoef(x, y=None, rowvar=True, bias=<no value>, ddof=<no value>)\r\n",
    "x : array_like\r\n",
    "    A 1-D or 2-D array containing multiple variables and observations.\r\n",
    "    Each row of `x` represents a variable, and each column a single\r\n",
    "    observation of all those variables. Also see `rowvar` below.\r\n",
    "y : array_like, optional\r\n",
    "    An additional set of variables and observations. `y` has the same\r\n",
    "    shape as `x`.\r\n",
    "rowvar : bool, optional\r\n",
    "    If `rowvar` is True (default), then each row represents a\r\n",
    "    variable, with observations in the columns. Otherwise, the relationship\r\n",
    "    is transposed: each column represents a variable, while the rows\r\n",
    "    contain observations.\r\n",
    "bias : _NoValue, optional\r\n",
    "    Has no effect, do not use.\r\n",
    "'''"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "最后，需要说明二维`Numpy`数组中统计函数的`axis`参数，它能够进行某一个维度下的统计特征计算，当`axis=0`时结果为列的统计指标，当`axis=1`时结果为行的统计指标："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 118,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1, 2, 3],\n",
       "       [4, 5, 6],\n",
       "       [7, 8, 9]])"
      ]
     },
     "execution_count": 118,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "target = np.arange(1,10).reshape(3,-1)\n",
    "target"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 119,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([12, 15, 18])"
      ]
     },
     "execution_count": 119,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#按照列来\r\n",
    "target.sum(0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 6, 15, 24])"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#按照行来\r\n",
    "target.sum(1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "### 5. 广播机制\n",
    "\n",
    "广播机制用于处理两个不同维度数组之间的操作，这里只讨论不超过两维的数组广播机制。\n",
    "\n",
    "【a】标量和数组的操作\n",
    "\n",
    "当一个标量和数组进行运算时，标量会自动把大小扩充为数组大小，之后进行逐元素操作："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 120,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[4., 4.],\n",
       "       [4., 4.]])"
      ]
     },
     "execution_count": 120,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "res = 3 * np.ones((2,2)) + 1\n",
    "#相当于res = 3 * np.ones((2,2))+1 * np.ones((2,2))\n",
    "res"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 121,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0.25, 0.25],\n",
       "       [0.25, 0.25]])"
      ]
     },
     "execution_count": 121,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "res = 1 / res\n",
    "res"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "【b】二维数组之间的操作\n",
    "\n",
    "当两个数组维度完全一致时，使用对应元素的操作，否则会报错，除非其中的某个数组的维度是$m×1$或者$1×n$，那么会扩充其具有$1$的维度为另一个数组对应维度的大小。例如，$1×2$数组和$3×2$数组做逐元素运算时会把第一个数组扩充为$3×2$，扩充时的对应数值进行赋值。但是，需要注意的是，如果第一个数组的维度是$1×3$，那么由于在第二维上的大小不匹配且不为$1$，此时报错。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 122,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1., 1.],\n",
       "       [1., 1.],\n",
       "       [1., 1.]])"
      ]
     },
     "execution_count": 122,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "res = np.ones((3,2))\n",
    "res"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 126,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[2., 3.],\n",
       "       [2., 3.],\n",
       "       [2., 3.]])"
      ]
     },
     "execution_count": 126,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "res * np.array([[2,3]]) # 扩充第一维度为3\r\n",
    "#相当于，也就是每个行向量和列向量相乘res * np.array([[2,3],[2,3],[2,3]])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 129,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[2., 2.],\n",
       "       [3., 3.],\n",
       "       [4., 4.]])"
      ]
     },
     "execution_count": 129,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "res * np.array([[2],[3],[4]]) # 扩充第二维度为2\r\n",
    "#相当于先把后面的变成2 * 3"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[2., 2.],\n",
       "       [2., 2.],\n",
       "       [2., 2.]])"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "res * np.array([[2]]) # 等价于两次扩充\r\n",
    "#相当于把后面的由1 * 1变成 1 * 3 再变成2 * 3"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "【c】一维数组与二维数组的操作\n",
    "\n",
    "当一维数组$A_k$与二维数组$B_{m,n}$操作时，等价于把一维数组视作$A_{1,k}$的二维数组，使用的广播法则与【b】中一致，当$k!=n$且$k,n$都不是$1$时报错。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 130,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[2., 2., 2.],\n",
       "       [2., 2., 2.]])"
      ]
     },
     "execution_count": 130,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.ones(3) + np.ones((2,3))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 132,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[2., 2., 2.],\n",
       "       [2., 2., 2.]])"
      ]
     },
     "execution_count": 132,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.ones(3) + np.ones((2,1))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 133,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[2., 2., 2.],\n",
       "       [2., 2., 2.]])"
      ]
     },
     "execution_count": 133,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.ones(1) + np.ones((2,3))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "### 6. 向量与矩阵的计算\n",
    "【a】向量内积：`dot`\n",
    "\n",
    "$$\\rm \\mathbf{a}\\cdot\\mathbf{b} = \\sum_ia_ib_i$$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 135,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "22"
      ]
     },
     "execution_count": 135,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = np.array([1,2,3])\n",
    "b = np.array([1,3,5])\n",
    "#1+6+15\n",
    "a.dot(b)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "【b】向量范数和矩阵范数：`np.linalg.norm`\n",
    "\n",
    "在矩阵范数的计算中，最重要的是`ord`参数，可选值如下："
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "| ord | norm for matrices | norm for vectors |\n",
    "| :---- | ----: | ----: |\n",
    "| None   | Frobenius norm | 2-norm |\n",
    "| 'fro'  | Frobenius norm  | / |\n",
    "| 'nuc'  | nuclear norm    | / |\n",
    "| inf    | max(sum(abs(x), axis=1))   | max(abs(x)) |\n",
    "| -inf   | min(sum(abs(x), axis=1))  |  min(abs(x)) |\n",
    "| 0      | /   |  sum(x != 0) |\n",
    "| 1      | max(sum(abs(x), axis=0))  |  as below |\n",
    "| -1     | min(sum(abs(x), axis=0))   |  as below |\n",
    "| 2      | 2-norm (largest sing. value) | as below |\n",
    "| -2     | smallest singular value    | as below |\n",
    "| other  | /   | sum(abs(x)**ord)**(1./ord) |\n",
    "\n",
    "$$math:`||A||_F = [\\sum_{i,j} abs(a_{i,j})^2]^{1/2}`$$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'\\nThis function is able to return one of eight different matrix norms,\\nor one of an infinite number of vector norms (described below), depending\\non the value of the ``ord`` parameter.\\n'"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.linalg.norm?\r\n",
    "'''\r\n",
    "This function is able to return one of eight different matrix norms,\r\n",
    "or one of an infinite number of vector norms (described below), depending\r\n",
    "on the value of the ``ord`` parameter.\r\n",
    "'''\r\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 136,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0, 1],\n",
       "       [2, 3]])"
      ]
     },
     "execution_count": 136,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "martix_target =  np.arange(4).reshape(-1,2)\n",
    "martix_target"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 147,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3.7416573867739413"
      ]
     },
     "execution_count": 147,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.linalg.norm(martix_target, 'fro')\r\n",
    "#The Frobenius norm is given by  [\\sum_{i,j} abs(a_{i,j})^2]^{1/2}\r\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 138,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "5.0"
      ]
     },
     "execution_count": 138,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.linalg.norm(martix_target, np.inf)\r\n",
    "#2+3 = 5?\r\n",
    "#max(sum(abs(x), axis=1))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 139,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3.702459173643833"
      ]
     },
     "execution_count": 139,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.linalg.norm(martix_target, 2)\r\n",
    "#2-norm (largest sing. value)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 140,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([0, 1, 2, 3])"
      ]
     },
     "execution_count": 140,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "vector_target =  np.arange(4)\n",
    "vector_target"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 141,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3.0"
      ]
     },
     "execution_count": 141,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.linalg.norm(vector_target, np.inf)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 142,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3.7416573867739413"
      ]
     },
     "execution_count": 142,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.linalg.norm(vector_target, 2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 143,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3.3019272488946263"
      ]
     },
     "execution_count": 143,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.linalg.norm(vector_target, 3)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "【c】矩阵乘法：`@`\n",
    "\n",
    "$$\\rm [\\mathbf{A}_{m\\times p}\\mathbf{B}_{p\\times n}]_{ij} = \\sum_{k=1}^p\\mathbf{A}_{ik}\\mathbf{B}_{kj}$$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0, 1],\n",
       "       [2, 3]])"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = np.arange(4).reshape(-1,2)\n",
    "a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[-4, -3],\n",
       "       [-2, -1]])"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "b = np.arange(-4,0).reshape(-1,2)\n",
    "b"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 150,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "22"
      ]
     },
     "execution_count": 150,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a@b\r\n",
    "#或者用dot np.dot(a,b)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "## 三、练习\n",
    "### Ex1：利用列表推导式写矩阵乘法\n",
    "一般的矩阵乘法根据公式，可以由三重循环写出，请将其改写为列表推导式的形式。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.7173159238588718\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "M1 = np.random.rand(2,3)\n",
    "M2 = np.random.rand(3,4)\n",
    "res = np.empty((M1.shape[0],M2.shape[1]))\n",
    "for i in range(M1.shape[0]):\n",
    "    for j in range(M2.shape[1]):\n",
    "        item = 0\n",
    "        for k in range(M1.shape[1]):\n",
    "            item += M1[i][k] * M2[k][j]\n",
    "        res[i][j] = item\n",
    "print(item)\n",
    "((M1@M2 - res) < 1e-15).all() # 排除数值误差"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[3.486907938125862]"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#列表推导式就是把多层for循环改成一行\r\n",
    "#这里写错的是直接把原来的循环复制出来\r\n",
    "res = [sum( M1[i][k] * M2[k][j]\r\n",
    "        for i in range(M1.shape[0])\r\n",
    "        for j in range(M2.shape[1])\r\n",
    "        for k in range(M1.shape[1]))\r\n",
    "]\r\n",
    "res\r\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[0.23655257469580804,\n",
       " 0.8514528274935084,\n",
       " 0.38247652284847355,\n",
       " 1.384121823271672,\n",
       " 0.11785110864376912,\n",
       " 0.2745800719792733,\n",
       " 0.23438428356520583,\n",
       " 0.7173159238588718]"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#参考答案：\r\n",
    "res = [sum( M1[i][k] * M2[k][j]\r\n",
    "        for k in range(M1.shape[1]))\r\n",
    "        for j in range(M2.shape[1])        \r\n",
    "        for i in range(M1.shape[0])\r\n",
    "]\r\n",
    "res"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "### Ex2：更新矩阵\n",
    "设矩阵 $A_{m×n}$ ，现在对 $A$ 中的每一个元素进行更新生成矩阵 $B$ ，更新方法是 $B_{ij}=A_{ij}\\sum_{k=1}^n\\frac{1}{A_{ik}}$ ，例如下面的矩阵为 $A$ ，则 $B_{2,2}=5\\times(\\frac{1}{4}+\\frac{1}{5}+\\frac{1}{6})=\\frac{37}{12}$ ，请利用 `Numpy` 高效实现。\n",
    "\n",
    "$$\\begin{split}A=\\left[ \\begin{matrix} 1 & 2 &3\\\\4&5&6\\\\7&8&9 \\end{matrix} \\right]\\end{split}$$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[1.83333333, 3.66666667, 5.5       ],\n",
       "       [2.46666667, 3.08333333, 3.7       ],\n",
       "       [2.65277778, 3.03174603, 3.41071429]])"
      ]
     },
     "execution_count": 52,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A = np.arange(1,10).reshape(3,3)\r\n",
    "#这里的运算优先级是关键\r\n",
    "#相当于B = A*((1/A).sum(1).reshape(-1,1))\r\n",
    "B = A*(1/A).sum(1).reshape(-1,1)\r\n",
    "B"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "### Ex3：卡方统计量\n",
    "\n",
    "设矩阵$A_{m\\times n}$，记$B_{ij} = \\frac{(\\sum_{i=1}^mA_{ij})\\times (\\sum_{j=1}^nA_{ij})}{\\sum_{i=1}^m\\sum_{i=1}^nA_{ij}}$，定义卡方值如下：\n",
    "$$\\chi^2 = \\sum_{i=1}^m\\sum_{j=1}^n\\frac{(A_{ij}-B_{ij})^2}{B_{ij}}$$\n",
    "请利用`Numpy`对给定的矩阵$A$计算$\\chi^2$ "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 64,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "A [[15 10 13 13 17]\n",
      " [19 13 15 12 14]\n",
      " [17 16 18 18 11]\n",
      " [16 17 17 18 11]\n",
      " [15 19 18 19 14]\n",
      " [13 10 13 15 10]\n",
      " [12 13 18 11 13]\n",
      " [13 13 17 10 11]]\n",
      "B [[14.14211438 13.08145581 15.20277296 13.67071057 11.90294627]\n",
      " [15.18197574 14.04332756 16.32062392 14.67590988 12.77816291]\n",
      " [16.63778163 15.38994801 17.88561525 16.08318891 14.0034662 ]\n",
      " [16.42980936 15.19757366 17.66204506 15.88214905 13.82842288]\n",
      " [17.67764298 16.35181976 19.0034662  17.08838821 14.87868284]\n",
      " [12.68630849 11.73483536 13.63778163 12.26343154 10.67764298]\n",
      " [13.93414211 12.88908146 14.97920277 13.46967071 11.72790295]\n",
      " [13.3102253  12.31195841 14.3084922  12.86655113 11.20277296]]\n",
      "11.842696601945802\n"
     ]
    }
   ],
   "source": [
    "np.random.seed(0)\n",
    "A = np.random.randint(10, 20, (8, 5))\n",
    "print('A',A)\n",
    "#原来写这句会导致B的维度错误 B = (A.sum(1) * A.sum(0).reshape(-1,1))/A.sum()\n",
    "B = A.sum(0)*A.sum(1).reshape(-1, 1)/A.sum()\n",
    "print('B',B)\n",
    "ka=((A-B)**2/B).sum()\n",
    "\n",
    "print(ka)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "### Ex4：改进矩阵计算的性能\n",
    "设$Z$为$m×n$的矩阵，$B$和$U$分别是$m×p$和$p×n$的矩阵，$B_i$为$B$的第$i$行，$U_j$为$U$的第$j$列，下面定义$\\displaystyle R=\\sum_{i=1}^m\\sum_{j=1}^n\\|B_i-U_j\\|_2^2Z_{ij}$，其中$\\|\\mathbf{a}\\|_2^2$表示向量$a$的分量平方和$\\sum_i a_i^2$。\n",
    "\n",
    "现有某人根据如下给定的样例数据计算$R$的值，请充分利用`Numpy`中的函数，基于此问题改进这段代码的性能。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 65,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "100566"
      ]
     },
     "execution_count": 65,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.random.seed(0)\n",
    "m, n, p = 100, 80, 50\n",
    "B = np.random.randint(0, 2, (m, p))\n",
    "U = np.random.randint(0, 2, (p, n))\n",
    "Z = np.random.randint(0, 2, (m, n))\n",
    "def solution(B=B, U=U, Z=Z):\n",
    "    L_res = []\n",
    "    for i in range(m):\n",
    "        for j in range(n):\n",
    "            norm_value = ((B[i]-U[:,j])**2).sum()\n",
    "            L_res.append(norm_value*Z[i][j])\n",
    "    return sum(L_res)\n",
    "solution(B, U, Z)\n",
    "#运行时间68ms"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(80,)\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "100566"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.random.seed(0)\r\n",
    "m, n, p = 100, 80, 50\r\n",
    "B = np.random.randint(0, 2, (m, p))\r\n",
    "U = np.random.randint(0, 2, (p, n))\r\n",
    "Z = np.random.randint(0, 2, (m, n))\r\n",
    "'''\r\n",
    "R=[sum(((B[i]-U[:,j])**2)\r\n",
    "    for i in range(m)\r\n",
    "    for j in range(n))\r\n",
    "]\r\n",
    "R \r\n",
    "然而这样做一点也不对，还是看答案吧\r\n",
    "答案中把B和U的差的平方展开，变成B和U的平方减去两项的内积\r\n",
    "B**2，U**2，B*U\r\n",
    "最关键的是shape对的上\r\n",
    "np.shape(B**2)=(100,50)\r\n",
    "np.shape(B**2.sum(1).reshape(-1,1))=(100,1)\r\n",
    "np.shape((U**2).sum(0))=(80,)\r\n",
    "'''\r\n",
    "#print(np.shape(B**2)) \r\n",
    "#print(np.shape((B**2).sum(1).reshape(-1,1)))\r\n",
    "#print(np.shape((U**2).sum(0)))\r\n",
    "(((B**2).sum(1).reshape(-1,1) + (U**2).sum(0) - 2*B@U)*Z).sum()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "### Ex5：连续整数的最大长度\n",
    "\n",
    "输入一个整数的`Numpy`数组，返回其中递增连续整数子数组的最大长度，正向是指递增方向。例如，输入\\[1,2,5,6,7\\]，\\[5,6,7\\]为具有最大长度的连续整数子数组，因此输出3；输入\\[3,2,1,2,3,4,6\\]，\\[1,2,3,4\\]为具有最大长度的连续整数子数组，因此输出4。请充分利用`Numpy`的内置函数完成。（提示：考虑使用`nonzero, diff`函数）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[False  True False False]\n",
      "[1 0 1 0 0 1]\n",
      "(array([0, 2, 5]),)\n"
     ]
    }
   ],
   "source": [
    "#判断开始条件a(n+1)-a(n)=1且a(n)-a(n-1)!=1 ,n=1开始 diff(x)!=1\r\n",
    "#判断结束条件a(k+1)-a(k)!=1or(k+1)=len(a)\r\n",
    "#比较每一段k-n\r\n",
    "#输出是(k-n)最大值\r\n",
    "x=[1,2,5,6,7]\r\n",
    "print(np.diff(x)!=1)\r\n",
    "print(np.r_[1,np.diff(x)!=1,1])\r\n",
    "print(np.nonzero(np.r_[1,np.diff(x)!=1,1]))\r\n",
    "#参考答案\r\n",
    "f = lambda x:np.diff(np.nonzero(np.r_[1,np.diff(x)!=1,1])).max()\r\n",
    "#分析:np.r_缝合出来1，一堆布尔值，1；放置前后两个1是为了方便下一步做差\r\n",
    "#nonzero 输出不重复的元素的位置\r\n",
    "#外层的diff用不重复的元素做差，再取最大值，就可以避免顺序问题"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "PaddlePaddle 2.0.0b0 (Python 3.5)",
   "language": "python",
   "name": "py35-paddle1.2.0"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
